<?php

/**
 * 这里做一个文章浏览排行榜
 * 根据实际情况，看来需要做成单例模式或者采取其他方式，不再每次都需要初始化操作
 * 1.尝试单例形式
 * 2.可尝试工厂模式
 * @author Administrator
 *
 */

class Phb
{
    
    private static $_instance = null; //用来保存实例对象
    
    private $_articleList = []; //文章数组
    
    private $_redis = null; //redis实例对象
    
    private $_pdo = null; // pdo连接对象
    
    
    
    /**
     * 构造方法（单例）
     * 初始化redis
     */
    private function __construct()
    {
        // 初始化redis
        $this->_redis = new \Redis();
        $this->_redis->connect('127.0.0.1',6379);
        $this->_redis->select(0);
        // 初始化数据
        $this->_setArticleList();
        // 存入redis
        $this->_setDatatoRedis();
        
    }
    
    /**
     * 公共方法用于获取实例
     */
    public static function getInstance()
    {
        if(!self::$_instance instanceof self){
            self::$_instance = new self;
        }
        
        return self::$_instance;
        
    }
    
    
    
    /**
     * 设置文章到数组中
     * @throws Exception
     */
    private function _setArticleList()
    {
        // 链接数据库获取数据读取
        try {
            $this->_pdo = new PDO("mysql:host=127.0.0.1;dbname=hlyy8_me","root","root");
        } catch (PDOException $e) {
            echo $e->getMessage();
        }
        
        // 读取文章列表
        $sql = "SELECT `id`,`title`,`pv` FROM `saas_post`"; //sql语句
        $stmt = $this->_pdo->prepare($sql); // 预处理
        $stmt->execute();
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
        if(!$result){
            throw new Exception('文章不存在',404);
        }
        
        $this->_articleList = $result;
        
    }
    
    /**
     * 将数组存入redis中
     * @throws Exception
     */
    private function _setDatatoRedis()
    {
        if (empty($this->_articleList)) {
            throw new Exception('文章列表数据为空，无法操作',404);
        }
        
        
        // 这里做两个方案  1.存入的是标题 2.存入的是id
        
        // 第一种方案
        foreach ($this->_articleList as  $value) {
            $this->_redis->zAdd('readTop',$value['pv'],$value['title']); // 这里使用文章列表中pv的值作为点击率，写入redis，进行排行。
        }
        
        
    }
    
    
    
    
    public function viewArticleId($id)
    {
        
    }
    
    /**
     * 禁止克隆
     */
    private function __clone()
    {
        
    }
    
    /**
     * 读取数据排行榜
     * @param number $offset
     * @param number $length
     * @throws Exception
     * @return array 排行榜数据
     */
    public function leaderboard($offset=1,$length=10)
    {
        // 根据数组实际情况，做-1数据处理
        $offset = $offset-1;
        $length = $length-1;
        
        $result = $this->_redis->zRevRange('readTop',$offset,$length);
        
        if (empty($result)) {
            throw new Exception('暂无排名',403);
        }
        
        return $result;
    }
}

$Phb1 = Phb::getInstance();
echo "<pre>";
print_r($Phb1->leaderboard());










